package cn.phecda.boot.common.lang.util;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

/**
 * <p>snowflake算法工具</p>
 *
 * @author wanpinwei
 */
@Slf4j
public class SnowflakeUtils {
    public static final String PROPERTY_WORKER_ID = "SNOWFLAKE_WORKER_ID";
    public static final String PROPERTY_DATACENTER_ID = "SNOWFLAKE_DATACENTER_ID";

    private static Snowflake snowflake;

    private SnowflakeUtils() {
    }

    private static synchronized void initSnowflake() {
        if (snowflake != null) {
            return;
        }

        long datacenterId = 1;
        String datacenterIdStr = System.getProperty(PROPERTY_DATACENTER_ID);
        if (StringUtils.isNotBlank(datacenterIdStr)) {
            try {
                datacenterId = Long.parseLong(datacenterIdStr);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException(
                        "Environment variable " + PROPERTY_DATACENTER_ID + " must be number");
            }
        }

        long workerId = 1;
        String workerIdStr = System.getProperty(PROPERTY_WORKER_ID);
        if (StringUtils.isNotBlank(workerIdStr)) {
            try {
                workerId = Long.parseLong(workerIdStr);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException(
                        "Environment variable " + PROPERTY_WORKER_ID + " must be number");
            }
        }

        snowflake = IdUtil.getSnowflake(workerId, datacenterId);

        log.info("|Phecda Boot Common|- Snowflake Id initialized [worker={}, datacenter={}]", workerId, datacenterId);
    }

    public static long nextId() {
        if (snowflake == null) {
            initSnowflake();
        }
        return snowflake.nextId();
    }

    public static long[] nextIds(int size) {
        Assert.isTrue(size > 0, "The value must be greater than zero");

        long[] ids = new long[size];
        for(int i = 0; i < size; i++) {
            ids[i] = nextId();
        }
        return ids;
    }

    public static String nextStrId() {
        if (snowflake == null) {
            initSnowflake();
        }
        return snowflake.nextIdStr();
    }

    public static String[] nextStrIds(int size) {
        Assert.isTrue(size > 0, "The value must be greater than zero");

        String[] ids = new String[size];
        for(int i = 0; i < size; i++) {
            ids[i] = nextStrId();
        }
        return ids;
    }
}
